package com.aloha.middleware.db.router.config;

import com.aloha.middleware.db.router.DBRouterAspect;
import com.aloha.middleware.db.router.dynamic.DynamicDataSource;
import com.aloha.middleware.db.router.dynamic.DynamicMybatisPlugin;
import com.aloha.middleware.db.router.strategy.IDBRouterStrategy;
import com.aloha.middleware.db.router.strategy.impl.DBRouterStrategyHashCode;
import org.apache.ibatis.plugin.Interceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aloha.middleware.db.router.config.DBRouterProperties.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author DaiZhiHeng
 * @description 配置类
 * @date 2023/7/9 9:38
 */
@Configuration
@EnableConfigurationProperties(DBRouterProperties.class)
public class DBRouterAutoConfiguration {

    @Resource
    public DBRouterProperties props;

    @Bean
    public DataSource dataSource() {
        String defaultName = props.getDefaultName();
        Map<String, DataSourceDefinition> dataSourceDefinitionMap = props.getDatasource();
        // 获取默认数据源的定义信息
        DataSourceDefinition defaultDefinition = dataSourceDefinitionMap.remove(defaultName);
        // 构建数据源
        Map<Object, Object> targetDataSources = dataSourceDefinitionMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> buildDataSource(entry.getValue())));
        // 创建动态数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(buildDataSource(defaultDefinition));
        // 设置动态切换的数据源
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }

    @Bean
    public TransactionTemplate transactionTemplate(DataSource dataSource) {
        // 编程式事务管理
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(dataSourceTransactionManager);
        transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        return transactionTemplate;
    }

    @Bean
    public IDBRouterStrategy dbRouterStrategy() {
        return new DBRouterStrategyHashCode(props);
    }

    @Bean(name = "db-router-aspect")
    @ConditionalOnMissingBean
    public DBRouterAspect dbRouterAspect(IDBRouterStrategy dbRouterStrategy) {
        return new DBRouterAspect(props, dbRouterStrategy);
    }

    @Bean
    public Interceptor plugin() {
        return new DynamicMybatisPlugin();
    }

    /**
     * 根据Definition构造数据源
     */
    private static DriverManagerDataSource buildDataSource(DataSourceDefinition definition) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(definition.getDriverClassName());
        dataSource.setUrl(definition.getUrl());
        dataSource.setUsername(definition.getUsername());
        dataSource.setPassword(definition.getPassword());
        return dataSource;
    }
}
